﻿// Decompiled with JetBrains decompiler
// Type: Commom.Util.Extensions
// Assembly: MT5Trade, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: 8045A2CB-DBD6-41AD-8804-F98CAC1BDC8D
// Assembly location: C:\projects\trade\trade_tool\trade0812\MT5Trade.dll

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;

#nullable enable
namespace Commom.Util;

public static class Extensions
{
  public static T SafeValue<T>(this T? value) where T : struct => value.GetValueOrDefault();

  public static int Value(this Enum instance)
  {
    return instance == null ? 0 : EnumUtil.GetValue(instance.GetType(), (object) instance);
  }

  public static TResult Value<TResult>(this Enum instance)
  {
    return instance == null ? default (TResult) : ConvertUtil.To<TResult>((object) instance.Value());
  }

  public static string Description(this Enum instance)
  {
    return instance == null ? string.Empty : EnumUtil.GetDescription(instance.GetType(), (object) instance);
  }

  public static string Join<T>(this IEnumerable<T> list, string quotes = "", string separator = ",")
  {
    return String.Join<T>(list, quotes, separator);
  }

  public static bool IsNullOrEmpty(this string data)
  {
    return string.IsNullOrEmpty(data) || string.IsNullOrEmpty(data.Trim());
  }

  public static string SafeString(this object input) => input?.ToString().Trim() ?? string.Empty;

  public static bool ToBool(this string obj) => ConvertUtil.ToBool((object) obj);

  public static bool? ToBoolOrNull(this string obj) => ConvertUtil.ToBoolOrNull((object) obj);

  public static int ToInt(this string obj) => ConvertUtil.ToInt((object) obj);

  public static int? ToIntOrNull(this string obj) => ConvertUtil.ToIntOrNull((object) obj);

  public static long ToLong(this string obj) => ConvertUtil.ToLong((object) obj);

  public static long? ToLongOrNull(this string obj) => ConvertUtil.ToLongOrNull((object) obj);

  public static double ToDouble(this string obj) => ConvertUtil.ToDouble((object) obj);

  public static double? ToDoubleOrNull(this string obj) => ConvertUtil.ToDoubleOrNull((object) obj);

  public static Decimal ToDecimal(this string obj) => ConvertUtil.ToDecimal((object) obj);

  public static Decimal? ToDecimalOrNull(this string obj)
  {
    return ConvertUtil.ToDecimalOrNull((object) obj);
  }

  public static DateTime ToDate(this string obj) => ConvertUtil.ToDate((object) obj);

  public static DateTime? ToDateOrNull(this string obj) => ConvertUtil.ToDateOrNull((object) obj);

  public static Guid ToGuid(this string obj) => ConvertUtil.ToGuid((object) obj);

  public static Guid? ToGuidOrNull(this string obj) => ConvertUtil.ToGuidOrNull((object) obj);

  public static List<Guid> ToGuidList(this string obj) => ConvertUtil.ToGuidList(obj);

  public static List<Guid> ToGuidList(this IList<string> obj)
  {
    return obj == null ? new List<Guid>() : obj.Select<string, Guid>((Func<string, Guid>) (t => t.ToGuid())).ToList<Guid>();
  }

  public static string ToStr(this object data) => Conv.ToString(data);

  public static bool ToBool(this object data) => Conv.ToBool(data);

  public static string ReplaceTxt(this string str, char oldChar, char newChar)
  {
    return !str.IsNullOrEmpty() ? str.Replace(oldChar, newChar) : string.Empty;
  }

  public static string ReplaceTxt(this string str, string oldStr, string newStr)
  {
    return !str.IsNullOrEmpty() ? str.Replace(oldStr, newStr) : string.Empty;
  }

  public static string FilterHtml(this string html) => String.StripHtml(html);

  public static List<string> StrToList(this string data, char spilts)
  {
    return data.IsNullOrEmpty() ? (List<string>) null : ((IEnumerable<string>) data.Split(spilts)).ToList<string>();
  }

  public static string ListToStr(this IList<string> data, string spilts)
  {
    return string.Join(spilts, (IEnumerable<string>) data);
  }

  public static string ListToStr(this IList<string> data, char charstr)
  {
    StringBuilder data1 = new StringBuilder(string.Empty);
    foreach (string str in (IEnumerable<string>) data)
      data1.AppendFormat("'{0}'{1}", (object) str, (object) charstr);
    return data1.ToStr().Trim(charstr);
  }

  public static string ConToStr(this string data, char charstr)
  {
    StringBuilder data1 = new StringBuilder(string.Empty);
    foreach (string str in data.Split(charstr))
      data1.AppendFormat("'{0}'{1}", (object) str, (object) charstr);
    return data1.ToStr().Trim(charstr);
  }

  public static string ObjectToParamString(this object data)
  {
    StringBuilder data1 = new StringBuilder();
    foreach (PropertyInfo property in data.GetType().GetProperties())
    {
      object obj = property.GetValue(data, (object[]) null);
      if (obj != null)
        data1.AppendFormat("{0}={1}&", (object) property.Name, obj);
    }
    return data1.ToStr().Trim('&');
  }

  public static string ToMd5String(this string str)
  {
    if (string.IsNullOrEmpty(str == null ? (string) null : str.Trim()))
      return "";
    byte[] hash = MD5.Create().ComputeHash(Encoding.Default.GetBytes(str));
    StringBuilder stringBuilder = new StringBuilder();
    for (int index = 0; index < hash.Length; ++index)
      stringBuilder.Append(hash[index].ToString("X2"));
    return stringBuilder.ToString();
  }

  public static double NextDouble(this Random random, double miniDouble, double maxiDouble)
  {
    return random != null ? random.NextDouble() * (maxiDouble - miniDouble) + miniDouble : 0.0;
  }

  public static string ToDateTimeString(this DateTime dateTime, bool removeSecond = false)
  {
    return removeSecond ? dateTime.ToString("yyyy-MM-dd HH:mm") : dateTime.ToString("yyyy-MM-dd HH:mm:ss");
  }

  public static string ToDateTimeString(this DateTime? dateTime, bool removeSecond = false)
  {
    return !dateTime.HasValue ? string.Empty : dateTime.Value.ToDateTimeString(removeSecond);
  }

  public static string ToDateString(this DateTime dateTime) => dateTime.ToString("yyyy-MM-dd");

  public static string ToDateString(this DateTime? dateTime)
  {
    return !dateTime.HasValue ? string.Empty : dateTime.Value.ToDateString();
  }

  public static string ToTimeString(this DateTime dateTime) => dateTime.ToString("HH:mm:ss");

  public static string ToTimeString(this DateTime? dateTime)
  {
    return !dateTime.HasValue ? string.Empty : dateTime.Value.ToTimeString();
  }

  public static string ToMillisecondString(this DateTime dateTime)
  {
    return dateTime.ToString("yyyy-MM-dd HH:mm:ss.fff");
  }

  public static string ToMillisecondString(this DateTime? dateTime)
  {
    return !dateTime.HasValue ? string.Empty : dateTime.Value.ToMillisecondString();
  }

  public static string ToChineseDateString(this DateTime dateTime)
  {
    return $"{dateTime.Year}年{dateTime.Month}月{dateTime.Day}日";
  }

  public static string ToChineseDateString(this DateTime? dateTime)
  {
    return !dateTime.HasValue ? string.Empty : dateTime.SafeValue<DateTime>().ToChineseDateString();
  }

  public static string ToyyyyMMdd(this DateTime dateTime)
  {
    return $"{dateTime.Year}{dateTime.Month}{dateTime.Day}";
  }

  public static string ToyyyyMMdd(this DateTime? dateTime)
  {
    return !dateTime.HasValue ? string.Empty : dateTime.SafeValue<DateTime>().ToyyyyMMdd();
  }

  public static string ToChineseDateTimeString(this DateTime dateTime, bool removeSecond = false)
  {
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.AppendFormat("{0}年{1}月{2}日", (object) dateTime.Year, (object) dateTime.Month, (object) dateTime.Day);
    stringBuilder.AppendFormat(" {0}时{1}分", (object) dateTime.Hour, (object) dateTime.Minute);
    if (!removeSecond)
      stringBuilder.AppendFormat("{0}秒", (object) dateTime.Second);
    return stringBuilder.ToString();
  }

  public static string ToChineseDateTimeString(this DateTime? dateTime, bool removeSecond = false)
  {
    return !dateTime.HasValue ? string.Empty : dateTime.Value.ToChineseDateTimeString(removeSecond);
  }

  public static string Description(this TimeSpan span)
  {
    StringBuilder stringBuilder = new StringBuilder();
    if (span.Days > 0)
      stringBuilder.AppendFormat("{0}天", (object) span.Days);
    if (span.Hours > 0)
      stringBuilder.AppendFormat("{0}小时", (object) span.Hours);
    if (span.Minutes > 0)
      stringBuilder.AppendFormat("{0}分", (object) span.Minutes);
    if (span.Seconds > 0)
      stringBuilder.AppendFormat("{0}秒", (object) span.Seconds);
    if (span.Milliseconds > 0)
      stringBuilder.AppendFormat("{0}毫秒", (object) span.Milliseconds);
    if (stringBuilder.Length > 0)
      return stringBuilder.ToString();
    return $"{span.TotalSeconds * 1000.0}毫秒";
  }

  public static string Description(this bool value) => !value ? "否" : "是";

  public static string Description(this bool? value)
  {
    return value.HasValue ? value.Value.Description() : "";
  }

  public static Expression Property(this Expression expression, string propertyName)
  {
    if (propertyName.All<char>((Func<char, bool>) (t => t != '.')))
      return (Expression) Expression.Property(expression, propertyName);
    string[] strArray = propertyName.Split('.');
    Expression expression1 = (Expression) null;
    for (int index = 0; index < strArray.Length; ++index)
      expression1 = index != 0 ? expression1.Property(strArray[index]) : (Expression) Expression.Property(expression, strArray[0]);
    return expression1;
  }

  public static Expression Property(this Expression expression, MemberInfo member)
  {
    return (Expression) Expression.MakeMemberAccess(expression, member);
  }

  public static Expression And(this Expression left, Expression right)
  {
    if (left == null)
      return right;
    return right == null ? left : (Expression) Expression.AndAlso(left, right);
  }

  public static Expression<Func<T, bool>> And<T>(
    this Expression<Func<T, bool>> left,
    Expression<Func<T, bool>> right)
  {
    if (left == null)
      return right;
    // ISSUE: reference to a compiler-generated field
    // ISSUE: reference to a compiler-generated field
    return right == null ? left : left.Compose<Func<T, bool>>(right, Expression.AndAlso);
  }

  public static Expression Or(this Expression left, Expression right)
  {
    if (left == null)
      return right;
    return right == null ? left : (Expression) Expression.OrElse(left, right);
  }

  public static Expression<Func<T, bool>> Or<T>(
    this Expression<Func<T, bool>> left,
    Expression<Func<T, bool>> right)
  {
    if (left == null)
      return right;
    // ISSUE: reference to a compiler-generated field
    // ISSUE: reference to a compiler-generated field
    return right == null ? left : left.Compose<Func<T, bool>>(right, Expression.OrElse);
  }

  public static object Value<T>(this Expression<Func<T, bool>> expression)
  {
    return Lambda.GetValue((Expression) expression);
  }

  public static Expression Equal(this Expression left, Expression right)
  {
    return (Expression) Expression.Equal(left, right);
  }

  public static Expression Equal(this Expression left, object value)
  {
    return Extensions.Equal(left, (Expression) Lambda.Constant(value, left));
  }

  public static Expression NotEqual(this Expression left, Expression right)
  {
    return (Expression) Expression.NotEqual(left, right);
  }

  public static Expression NotEqual(this Expression left, object value)
  {
    return Extensions.NotEqual(left, (Expression) Lambda.Constant(value, left));
  }

  public static Expression Greater(this Expression left, Expression right)
  {
    return (Expression) Expression.GreaterThan(left, right);
  }

  public static Expression Greater(this Expression left, object value)
  {
    return Extensions.Greater(left, (Expression) Lambda.Constant(value, left));
  }

  public static Expression GreaterEqual(this Expression left, Expression right)
  {
    return (Expression) Expression.GreaterThanOrEqual(left, right);
  }

  public static Expression GreaterEqual(this Expression left, object value)
  {
    return Extensions.GreaterEqual(left, (Expression) Lambda.Constant(value, left));
  }

  public static Expression Less(this Expression left, Expression right)
  {
    return (Expression) Expression.LessThan(left, right);
  }

  public static Expression Less(this Expression left, object value)
  {
    return Extensions.Less(left, (Expression) Lambda.Constant(value, left));
  }

  public static Expression LessEqual(this Expression left, Expression right)
  {
    return (Expression) Expression.LessThanOrEqual(left, right);
  }

  public static Expression LessEqual(this Expression left, object value)
  {
    return Extensions.LessEqual(left, (Expression) Lambda.Constant(value, left));
  }

  public static Expression StartsWith(this Expression left, object value)
  {
    return left.Call(nameof (StartsWith), new Type[1]
    {
      typeof (string)
    }, value);
  }

  public static Expression EndsWith(this Expression left, object value)
  {
    return left.Call(nameof (EndsWith), new Type[1]
    {
      typeof (string)
    }, value);
  }

  public static Expression Contains(this Expression left, object value)
  {
    return left.Call(nameof (Contains), new Type[1]
    {
      typeof (string)
    }, value);
  }

  public static Expression Operation(this Expression left, Operator @operator, object value)
  {
    switch (@operator)
    {
      case Operator.Equal:
        return left.Equal(value);
      case Operator.NotEqual:
        return left.NotEqual(value);
      case Operator.Greater:
        return left.Greater(value);
      case Operator.GreaterEqual:
        return left.GreaterEqual(value);
      case Operator.Less:
        return left.Less(value);
      case Operator.LessEqual:
        return left.LessEqual(value);
      case Operator.Starts:
        return left.StartsWith(value);
      case Operator.Ends:
        return left.EndsWith(value);
      case Operator.Contains:
        return left.Contains(value);
      default:
        throw new NotImplementedException();
    }
  }

  public static Expression Operation(this Expression left, Operator @operator, Expression value)
  {
    switch (@operator)
    {
      case Operator.Equal:
        return Extensions.Equal(left, value);
      case Operator.NotEqual:
        return Extensions.NotEqual(left, value);
      case Operator.Greater:
        return Extensions.Greater(left, value);
      case Operator.GreaterEqual:
        return Extensions.GreaterEqual(left, value);
      case Operator.Less:
        return Extensions.Less(left, value);
      case Operator.LessEqual:
        return Extensions.LessEqual(left, value);
      default:
        throw new NotImplementedException();
    }
  }

  public static Expression Call(
    this Expression instance,
    string methodName,
    params Expression[] values)
  {
    if (instance == null)
      throw new ArgumentNullException(nameof (instance));
    MethodInfo method = instance.Type.GetMethod(methodName);
    return method == (MethodInfo) null ? (Expression) null : (Expression) Expression.Call(instance, method, values);
  }

  public static Expression Call(
    this Expression instance,
    string methodName,
    params object[] values)
  {
    if (instance == null)
      throw new ArgumentNullException(nameof (instance));
    MethodInfo method = instance.Type.GetMethod(methodName);
    if (method == (MethodInfo) null)
      return (Expression) null;
    // ISSUE: reference to a compiler-generated field
    // ISSUE: reference to a compiler-generated field
    return values == null || values.Length == 0 ? (Expression) Expression.Call(instance, method) : (Expression) Expression.Call(instance, method, (IEnumerable<Expression>) ((IEnumerable<object>) values).Select<object, ConstantExpression>(Expression.Constant));
  }

  public static Expression Call(
    this Expression instance,
    string methodName,
    Type[] paramTypes,
    params object[] values)
  {
    if (instance == null)
      throw new ArgumentNullException(nameof (instance));
    MethodInfo method = instance.Type.GetMethod(methodName, paramTypes);
    if (method == (MethodInfo) null)
      return (Expression) null;
    // ISSUE: reference to a compiler-generated field
    // ISSUE: reference to a compiler-generated field
    return values == null || values.Length == 0 ? (Expression) Expression.Call(instance, method) : (Expression) Expression.Call(instance, method, (IEnumerable<Expression>) ((IEnumerable<object>) values).Select<object, ConstantExpression>(Expression.Constant));
  }

  internal static Expression<T> Compose<T>(
    this Expression<T> first,
    Expression<T> second,
    Func<Expression, Expression, Expression> merge)
  {
    Expression expression = ParameterRebinder.ReplaceParameters(first.Parameters.Select((f, i) => new
    {
      f = f,
      s = second.Parameters[i]
    }).ToDictionary(p => p.s, p => p.f), second.Body);
    return Expression.Lambda<T>(merge(first.Body, expression), (IEnumerable<ParameterExpression>) first.Parameters);
  }

  public static Expression<TDelegate> ToLambda<TDelegate>(
    this Expression body,
    params ParameterExpression[] parameters)
  {
    return body == null ? (Expression<TDelegate>) null : Expression.Lambda<TDelegate>(body, parameters);
  }

  public static Expression<Func<T, bool>> ToPredicate<T>(
    this Expression body,
    params ParameterExpression[] parameters)
  {
    return body.ToLambda<Func<T, bool>>(parameters);
  }

  public static object GetPropertyValue(this MemberInfo member, object instance)
  {
    if (member == (MemberInfo) null)
      throw new ArgumentNullException(nameof (member));
    if (instance == null)
      throw new ArgumentNullException(nameof (instance));
    return instance.GetType().GetProperty(member.Name)?.GetValue(instance);
  }

  public static string RemoveEnd(this string value, string removeValue)
  {
    return String.RemoveEnd(value, removeValue);
  }

  public static void CheckNull(this object obj, string parameterName)
  {
    if (obj == null)
      throw new ArgumentNullException(parameterName);
  }

  public static bool IsEmpty(this string value) => string.IsNullOrWhiteSpace(value);

  public static bool IsEmpty(this Guid value) => value == Guid.Empty;

  public static bool IsEmpty(this Guid? value)
  {
    if (!value.HasValue)
      return true;
    Guid? nullable = value;
    Guid empty = Guid.Empty;
    return nullable.HasValue && nullable.GetValueOrDefault() == empty;
  }

  public static bool IsEmpty<T>(this IEnumerable<T> value) => value == null || !value.Any<T>();
}
